/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <pthread.h>

#include "keyboard_srv_client.h"
#include "string_ex.h"
#include "datetime_ex.h"
#include "ipc_skeleton.h"
#include "iservice_registry.h"
#include "if_system_ability_manager.h"
#include "system_ability_definition.h"
#include "keyboard_errors.h"
#include "keyboard_common.h"
#include "hilog_wrapper.h"

namespace SwanLink {
namespace  Finance{
using namespace OHOS;
KeyboardSrvClient::KeyboardSrvClient() {}
KeyboardSrvClient::~KeyboardSrvClient() {}

ErrCode KeyboardSrvClient::Connect()
{
    std::lock_guard<std::mutex> lock(mutex_);
    if (proxy_ != nullptr) {
        return ERR_OK;
    }
    sptr<ISystemAbilityManager> sysMgr =
            SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    if (sysMgr == nullptr) {
        KEYBOARD_HILOGE(KEYBOARD_SRV, "failed to GetSystemAbilityManager, %{public}d",
            FINANCE_KEYBOARD_SERVICE_ID);
        return E_GET_SYSTEM_ABILITY_MANAGER_FAILED;
    }
    sptr<IRemoteObject> remoteObject_ =
            sysMgr->CheckSystemAbility(FINANCE_KEYBOARD_SERVICE_ID);
    if (remoteObject_ == nullptr) {
        KEYBOARD_HILOGE(KEYBOARD_SRV, "failed to GetSystemAbility by %{public}d",
            FINANCE_KEYBOARD_SERVICE_ID);
        return E_GET_SYSTEM_ABILITY_MANAGER_FAILED;
    }

    deathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new KeyboardSrvDeathRecipient());
    if (deathRecipient_ == nullptr) {
        KEYBOARD_HILOGE(KEYBOARD_SRV, "failed to Create DeathRecipinent,%{public}d", FINANCE_KEYBOARD_SERVICE_ID);
        return ERR_NO_MEMORY;
    }
    if ((remoteObject_->IsProxyObject()) && (!remoteObject_->AddDeathRecipient(deathRecipient_))) {
        KEYBOARD_HILOGW(KEYBOARD_SRV, "Add death recipient to failed,%{public}d", FINANCE_KEYBOARD_SERVICE_ID);
        return E_ADD_DEATH_RECIPIENT_FAILED;
    }

    proxy_ = iface_cast<IKeyboardSrv>(remoteObject_);
    return ERR_OK;
}

void KeyboardSrvClient::ResetProxy(const wptr<IRemoteObject>& remote)
{
    std::lock_guard<std::mutex> lock(mutex_);
    RETURN_IF(proxy_ == nullptr);
    auto serviceRemote = proxy_->AsObject();
    if ((serviceRemote != nullptr) && (serviceRemote == remote.promote())) {
        serviceRemote->RemoveDeathRecipient(deathRecipient_);
        proxy_ = nullptr;
    }
}

void KeyboardSrvClient::KeyboardSrvDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& remote)
{
    if (remote == nullptr) {
        return;
    }
    KeyboardSrvClient::GetInstance().ResetProxy(remote);
}

bool KeyboardSrvClient::IsSM4Enabled(int handle)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "IsSM4Enabled failed");
        return false;
    }
    return proxy_->IsSM4Enabled(handle);
}

int KeyboardSrvClient::GetSN(int handle, char sn[], int &len)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "GetSN failed");
        return -1;
    }
    return proxy_->GetSN(handle, sn, len);
}

int KeyboardSrvClient::CalculateMAC(int handle, const KeyInfo& key,
                        char plain[], int len, char enc_data[], int &enc_len)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "CalculateMAC failed");
        return -1;
    }
    return proxy_->CalculateMAC(handle, key, plain, len, enc_data, enc_len);
}

int KeyboardSrvClient::EncryptData(int handle, const KeyInfo& key,
                        char plain[], int len, char enc_data[], int &len_enc)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "EncryptData failed");
        return -1;
    }
    return proxy_->EncryptData(handle, key, plain, len, enc_data, len_enc);
}

int KeyboardSrvClient::SetPINLength(int handle, int minLen, int maxLen)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "SetPINLength failed");
        return -1;
    }
    return proxy_->SetPINLength(handle, minLen, maxLen);
}

int KeyboardSrvClient::SetTextMode(int handle, TextMode mode)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "SetTextMode failed");
        return -1;
    }
    return proxy_->SetTextMode(handle, mode);
}

void KeyboardSrvClient::ClearTextMode(int handle)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "ClearTextMode failed");
        return;
    }
    return proxy_->ClearTextMode(handle);
}

int KeyboardSrvClient::LoadMasterKey(int handle, KeyID masterKeyID,
                        unsigned char *KeyValue)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "LoadMasterKey failed");
        return -1;
    }
    return proxy_->LoadMasterKey(handle, masterKeyID, KeyValue);
}

int KeyboardSrvClient::LoadUserKey(int handle, KeyID masterKeyID,
                        userKeyType user_Key_Type, unsigned char *KeyValue)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "LoadUserKey failed");
        return -1;
    }
    return proxy_->LoadUserKey(handle, masterKeyID, user_Key_Type, KeyValue);
}

int KeyboardSrvClient::UpdateMasterKey(int handle, KeyID masterKeyID,
                        unsigned char *KeyValue)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "UpdateMasterKey failed");
        return -1;
    }
    return proxy_->UpdateMasterKey(handle, masterKeyID, KeyValue);
}

int KeyboardSrvClient::UpdateUserKey(int handle, KeyID masterKeyID,
                        userKeyType user_Key_Type, unsigned char *KeyValue)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "UpdateUserKey failed");
        return -1;
    }
    return proxy_->UpdateUserKey(handle, masterKeyID, user_Key_Type, KeyValue);
}

int KeyboardSrvClient::DeleteUserKey(int handle, KeyID masterKeyID,
                        userKeyType user_Key_Type)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "DeleteUserKey failed");
        return -1;
    }
    return proxy_->DeleteUserKey(handle, masterKeyID, user_Key_Type);
}

void KeyboardSrvClient::ListenForPin(int handle, PinListener* listener,
                         int timeout)
{
    int ret = Connect();
    if (ret != ERR_OK) {
        KEYBOARD_HILOGE(KEYBOARD_JS_NAPI, "ListenForPin failed");
        return;
    }
    proxy_->ListenForPin(handle, listener, timeout);
}
} // namespace Finance
} // namespace SwanLink
